#ifndef __SERVER_H_
#define __SERVER_H_

/**
 * @file server.h
 * @brief Serveur de fichier.
 * @author Florian.B
 * @version 0.1
 * @date 4 avril 2012
 *
 * Serveur de fichier autonomme. Il suffit d'utiliser la fonction serveur et il se débrouille.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
/**
 *@param CONTINU est la variable de boucle des threads qui permet de leur dire de s'arrêter
 */
extern volatile sig_atomic_t CONTINUE_SERVER;

#include "mutexqueue.h"
#include "mutexlist.h"
#include "filemanagement.h"
#include "mutexfile.h"
#include "../tools/toolsclientserver.h"

/**
 * @struct Server
 * @brief Objet Server
 *
 * Server est un petit objet qui permet de réaliser un serveur de fichier. Il possède des threads de services qui pourront répondres aux différents clients.
 */
typedef struct _Server
{
  char *port /*!< Le numéro du port de connexion. */;
  int socket /*!< La socket d'écoute de nouveau client. */;
  int nbThread /*!< Le nombre de threads de service. */;
  pthread_t *tabThread /*!< Sauvegarde les threads de service. */;
  MutexFile mutexFile /*!< MutexFile pour gérer les fichiers qui sont utilisé par un client. */;
  MutexList mutexList; /*!< MutexList pour gérer les commandes des clients. */
  int socketpair[2]; /*!< Socket pour l’arrêt des threads de sevices. */
  int socketpairClient[2]; /*!< Socket pour la gestion des clients. */
  int socketpairService[2]; /*!< Socket pour renvoyer un client au thread de gestion de clients à partir des threads de service. */
  char *folder; /*!< Répertoire de partage. */
  int nbSocketAttente; /*!< Le nombre de socket en attente dans le serveur. */
}Server;

/**
 * @enum ServerClientOrder
 * @brief Les différentes commandes que peut éxecuter le server.
 *
 * ServerClientOrder est une série de constantes prédéfinies pour diverses fonction futur de l'objet server.
 */
typedef enum
  {
    SERVERCLIENTORDER_LIST, /*!< Le client demande au serveur la liste des fichiers */
    SERVERCLIENTORDER_GETF, /*!< Le client demande un fichier */
    SERVERCLIENTORDER_FREE, /*!< Le client libère un fichier */
    SERVERCLIENTORDER_QUIT, /*!< Le client ferme la connexion */
    SERVERCLIENTORDER_ERR, /*!< La commande envoyer par le client n'existe pas */
    SERVERCLIENTORDER_NB_RET /*!< Le nombre de commande que peut éxecuter le serveur */
  }ServerClientOrder;

/**
 * @enum ServerOrder
 * @brief Les différentes commandes que peut envoyer le serveur.
 *
 * ServerOrder est une série de constantes prédéfinies pour diverses fonction futur de l'objet server.
 */
typedef enum
  {
    SERVERORDER_FICH, /*!< Envoye d'un nom de fichier. */
    SERVERORDER_ENDL, /*!< Fin de la liste de fichier. */
    SERVERORDER_NONE, /*!< Le fichier n'existe pas. */
    SERVERORDER_BUSY, /*!< Le fichier est occupé. */
    SERVERORDER_SIZE, /*!< La taille du fichier à envoyer. */
    SERVERORDER_HELO, /*!< Début de connexion. */
    SERVERORDER_RCPT, /*!< Contenu de la commande qu'il à reçu */
    SERVERORDER_FAIL, /*!< La commande reçu n'existe pas */
    SERVERORDER_NB_RET /*!< Le nombre de commande que peut éxecuter le serveur */
  }ServerOrder;

/**
 * @enum ServerReturn
 * @brief Constantes de retour.
 *
 * ServerReturn est une série de constantes prédéfinies pour diverses futures fonctions de l'objet Server.
 */
typedef enum
  {
    SERVER_SUCCESS, /*!< Succès. */
    SERVER_ERR, /*!< Erreur. */
    SERVER_QUIT, /*!< Le server se ferme. */
    SERVER_SOCKET, /*!< Réception sur un socket d’un client. */
    SERVER_CLIENT_QUIT, /*!< Un client veut terminer la transaction. */
    SERVER_CON_ERR, /*!< Problème de connexion avec le client. */
    SERVER_NB_RET /*!< Nombre total de constantes de retour. */
  }ServerReturn;

/**
 * @fn void server(const int nbThread, const char *port, const int nbSocketAttente)
 * @brief crée le serveur cette fonction se termine lors de la fermeture du serveur.
 *
 * @param nbThread Le nombre de thread de service.
 * @param port Le port de connexion du programme.
 * @param nbSocketAttente Le nombre de socket en attente dans la file d'attente.
 */
void server(const int nbThread, const char *port, const char *directory, const int nbSocketAttente);

/**
 * @fn int creationSocket_Server(const char *port)
 * @brief Crée une socket d'attente de connexion client.
 *
 * @param port Le port d'écoute de la socket.
 * @return La socket nouvellement créée, Si la création n'est pas possible, le programme est terminé avec le code erreur 1.
 */
int creationSocket_Server(const char * port);

/**
 * @fn int attenteConnexion_Server(int socket)
 * @brief Attente d'une connexion sur la socket socket.
 *
 * @param socket La socket d'écoute.
 * @return La socket de connexion d'un client. NB : Elle est indépandante de la socket d'écoute.
 */
int attenteConnexion_Server(int socket);

#endif
